package com.agileboot.admin.controller.performance;

import com.agileboot.admin.controller.common.QiniuService;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.utils.file.MultipartFileUtils;
import com.agileboot.common.utils.poi.CustomExcelUtil;
import com.agileboot.domain.performance.submission.SubmissionApplicationService;
import com.agileboot.domain.performance.submission.command.AddSubmissionCommand;
import com.agileboot.domain.performance.submission.command.BatchReviewSubmissionCommand;
import com.agileboot.domain.performance.submission.command.UpdateSubmissionCommand;
import com.agileboot.domain.performance.submission.dto.SubmissionDTO;
import com.agileboot.domain.performance.submission.dto.SubmissionExcelDTO;
import com.agileboot.domain.performance.submission.dto.SubmissionExcelConverter;
import com.agileboot.domain.performance.submission.query.SubmissionQuery;
import com.agileboot.domain.system.file.FileApplicationService;
import com.agileboot.domain.system.file.db.SysFileEntity;
import com.agileboot.domain.system.file.dto.SysFileDTO;
import com.agileboot.domain.system.file.query.SysFileQuery;
import com.agileboot.infrastructure.annotations.ratelimit.RateLimit;
import com.agileboot.infrastructure.thread.ThreadPoolManager;
import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 绩效上报项控制器
 */
@Tag(name = "绩效上报项API", description = "绩效上报项相关的增删查改")
@RestController
@RequestMapping("/performance/submission")
@RequiredArgsConstructor
@Slf4j
public class SubmissionController {

    private final SubmissionApplicationService submissionApplicationService;
    private final FileApplicationService fileApplicationService;
    private final QiniuService qiniuService = new QiniuService();

    @Operation(summary = "获取绩效上报项列表")
    @GetMapping("/list")
    public ResponseDTO<PageDTO<SubmissionDTO>> list(SubmissionQuery query) {
        PageDTO<SubmissionDTO> pageDTO = submissionApplicationService.getSubmissionList(query);
        return ResponseDTO.ok(pageDTO);
    }

    @Operation(summary = "获取绩效上报项详情")
    @GetMapping("/{id}")
    public ResponseDTO<SubmissionDTO> getInfo(@PathVariable Long id) {
        SubmissionDTO submissionDTO = submissionApplicationService.getSubmissionInfo(id);
        return ResponseDTO.ok(submissionDTO);
    }

    @Operation(summary = "新增绩效上报项")
    @PostMapping
    public ResponseDTO<Void> add(@RequestBody AddSubmissionCommand addCommand) {
        submissionApplicationService.addSubmission(addCommand);
        return ResponseDTO.ok();
    }

    @Operation(summary = "修改绩效上报项")
    @PutMapping
    public ResponseDTO<Void> edit(@RequestBody UpdateSubmissionCommand updateCommand) {
        submissionApplicationService.updateSubmission(updateCommand);
        return ResponseDTO.ok();
    }

    @Operation(summary = "删除绩效上报项")
    @DeleteMapping
    public ResponseDTO<Void> delete(@RequestBody List<Long> ids) {
        submissionApplicationService.deleteSubmission(ids);
        return ResponseDTO.ok();
    }

    @Operation(summary = "批量提交绩效上报项")
    @PostMapping("/batchSubmit")
    public ResponseDTO<Void> batchSubmit(@RequestBody List<Long> idList) {
        submissionApplicationService.batchSubmit(idList);
        return ResponseDTO.ok();
    }

    @Operation(summary = "批量审核绩效上报项")
    @PostMapping("/batchReview")
    public ResponseDTO<Void> batchReview(@RequestBody BatchReviewSubmissionCommand command) {
        SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
        submissionApplicationService.batchReview(loginUser, command);
        return ResponseDTO.ok();
    }

    /**
     * 导出所有绩效上报项
     * @param response HttpServletResponse
     * @param query 查询条件
     */
    @Operation(summary = "导出绩效上报项")
    @GetMapping("/excel")
    public void export(HttpServletResponse response, SubmissionQuery query) {
        List<SubmissionDTO> all = submissionApplicationService.getSubmissionListAll(query);
        List<SubmissionExcelDTO> excelList = SubmissionExcelConverter.convertList(all);
        CustomExcelUtil.writeToResponse(excelList, SubmissionExcelDTO.class, response);
    }

    /**
     * 异步导出绩效上报项
     * 每10分钟只能请求一次（全局限流）
     * @param query 查询条件
     */
    @Operation(summary = "异步导出绩效上报项")
    @PostMapping("/asyncExport")
    @RateLimit(key = "submission:async:export", time = 60, maxCount = 1, limitType = RateLimit.LimitType.GLOBAL, cacheType = RateLimit.CacheType.REDIS)
    public ResponseDTO<Void> asyncExport(@RequestBody SubmissionQuery query) {
        SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
        Long userId = loginUser.getUserId();
        
        // 异步执行导出任务
        ThreadPoolManager.execute(() -> {
            try {
                log.info("开始异步导出绩效上报项，用户ID: {}", userId);
                
                // 1. 查询数据
                List<SubmissionDTO> all = submissionApplicationService.getSubmissionListAll(query);
                int dataCount = all.size();
                
                // 2. 转换为Excel格式
                List<SubmissionExcelDTO> excelList = SubmissionExcelConverter.convertList(all);
                
                // 3. 生成Excel文件到内存
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                CustomExcelUtil.writeToOutputStream(excelList, SubmissionExcelDTO.class, outputStream);
                byte[] excelBytes = outputStream.toByteArray();
                
                // 4. 生成文件名
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                String fileName = "绩效上报项导出_" + sdf.format(new Date()) + ".xlsx";
                
                // 5. 转换为MultipartFile
                MultipartFile multipartFile = MultipartFileUtils.createMultipartFile(
                    excelBytes, 
                    fileName, 
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                );
                
                // 6. 上传到七牛云
                String uploadToken = qiniuService.getUploadToken();
                Configuration cfg = new Configuration(com.qiniu.storage.Region.autoRegion());
                UploadManager uploadManager = new UploadManager(cfg);
                String key = "performance/submission/export/" + fileName;
                Response response = uploadManager.put(multipartFile.getInputStream(), key, uploadToken, null, null);
                DefaultPutRet putRet = response.jsonToObject(DefaultPutRet.class);
                String fileUrl = "http://cloud-file.dingyangmy.cn/" + putRet.key;
                
                // 7. 保存文件信息到数据库
                SysFileEntity fileEntity = new SysFileEntity();
                fileEntity.setFileName(fileName);
                fileEntity.setFileKey(putRet.key);
                fileEntity.setFileSuffix("xlsx");
                fileEntity.setFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                fileEntity.setFileSize((long) excelBytes.length);
                fileEntity.setStorageType("qiniu");
                fileEntity.setUrl(fileUrl);
                fileEntity.setBizType("performance_submission_export");
                fileEntity.setBizId(null);
                fileEntity.setCreatorId(userId);
                fileEntity.setRemark("数据数量: " + dataCount);
                
                fileApplicationService.saveFileInfo(fileEntity);
                
                log.info("异步导出完成，文件ID: {}, 数据数量: {}", fileEntity.getFileId(), dataCount);
                
            } catch (Exception e) {
                log.error("异步导出绩效上报项失败", e);
            }
        });
        
        return ResponseDTO.ok();
    }

    /**
     * 查询导出的绩效上报项Excel文件列表
     * @param query 查询条件
     */
    @Operation(summary = "查询导出的绩效上报项Excel文件列表")
    @GetMapping("/exportFiles")
    public ResponseDTO<PageDTO<SysFileDTO>> getExportFiles(SysFileQuery query) {
        // 只查询绩效上报项导出的文件
        query.setBizType("performance_submission_export");
        PageDTO<SysFileDTO> pageDTO = fileApplicationService.getFileList(query);
        
        // 从备注中提取数据数量
        if (pageDTO.getRows() != null) {
            for (SysFileDTO fileDTO : pageDTO.getRows()) {
                if (fileDTO.getRemark() != null && fileDTO.getRemark().startsWith("数据数量: ")) {
                    try {
                        String countStr = fileDTO.getRemark().substring("数据数量: ".length());
                        fileDTO.setDataCount(Integer.parseInt(countStr.trim()));
                    } catch (Exception e) {
                        log.warn("解析数据数量失败: {}", fileDTO.getRemark());
                    }
                }
            }
        }
        
        return ResponseDTO.ok(pageDTO);
    }
}
